package com.aaa.jvmtest.directmemory;

import sun.misc.Unsafe;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;

/**
 * 直接内存释放及原理
 * 可打开任务管理器查看内存占用
 * 直接内存不受垃圾回收管理，释放是因为调用unSafe
 *
 * @author Tu
 * @date 2022/6/15 15:14
 */
public class DirectMemoryRelease {

    private static final int _1G = 1024 * 1024 * 1024;

    public static void main(String[] args) throws IOException {
        releaseShow();
        //releaseTheory();
    }

    /**
     * 内存释放演示
     * 检验禁用显示垃圾回收，是否释放直接内存 添加参数：-XX:+DisableExplicitGC 禁用显式回收
     *
     * @throws IOException
     */
    public static void releaseShow() throws IOException {
        //声明1G的直接内存
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1G);
        System.out.println("分配完毕-------");
        //阻塞，直到输入字符
        System.in.read();
        System.out.println("开始释放-------");
        byteBuffer = null;
        //调用垃圾回收 添加参数后无效
        System.gc();
        System.in.read();
    }

    /**
     * 直接内存回收验证  不是通过GC，是通过Unsafe对象
     */
    public static void releaseTheory() throws IOException {
        Unsafe unsafe = getUnsafe();
        //分配内存方法 allocateMemory  base:分配的直接内存的地址
        long base = unsafe.allocateMemory(_1G);
        unsafe.setMemory(base, _1G, (byte) 0);
        System.in.read();

        //释放内存  根据base(地址)去释放直接内存，只能手动通过freeMemory调用(不自动)
        unsafe.freeMemory(base);
        System.in.read();
    }

    /**
     * 获取Unsafe对象
     *
     * @return
     */
    public static Unsafe getUnsafe() {
        try {
            //反射获取Unsafe对象
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            Unsafe unsafe = (Unsafe) theUnsafe.get(null);
            return unsafe;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
